#include "gtest-qt.h"
#include "gtest/gtest.h"
#include "gmock/gmock.h"

#include "tasks/taskboardrequest.h"
#include "tasks/taskthreadrequest.h"
#include "tasks/taskattachmentrequest.h"
#include "tasks/taskrequest.h"
#include "mockobjects/mockconnector.h"
#include "mockobjects/mockrequest.h"
#include "taskrequestsignalspy.h"

namespace
{
	using namespace Wishmaster;
	using namespace MockObjects;
	using ::testing::_;
	using ::testing::Return;

	class TestTaskRequest : public ::testing::Test
	{
	public:
		TestTaskRequest() : defaultThreadId("chan", "/b/", 123456),
				defaultPostId(defaultThreadId, 123457) {}

		ThreadId defaultThreadId;
		PostId defaultPostId;
	protected:
		void verifyTaskBoardRequest(const QString& chanName, const QString& boardId,
									const TaskBoardRequest& rq)
		{
			ASSERT_EQ(TaskRequest::rtBoard, rq.requestType());
			ASSERT_EQ(chanName, rq.chanName());
			ASSERT_EQ(boardId, rq.boardId());
		}

		void verifyTaskThreadRequest(const ThreadId& threadId, const TaskThreadRequest& rq)
		{
			ASSERT_EQ(TaskRequest::rtThread, rq.requestType());
			ASSERT_EQ(threadId, rq.threadId());
		}

		void verifyTaskAttachmentRequest(const PostId& postId, int attachmentIndex,
										 const TaskAttachmentRequest& rq)
		{
			ASSERT_EQ(TaskRequest::rtAttachment, rq.requestType());
			ASSERT_EQ(postId, rq.postId());
			ASSERT_EQ(attachmentIndex, rq.attachmentIndex());
		}

		MockRequestPtr makeMockRequest()
		{
			MockRequest* rq = new MockRequest();
			ON_CALL(*rq, contentType()).WillByDefault(Return(QString("application/html")));
			return MockRequestPtr(rq);
		}
	};

	TEST_F(TestTaskRequest, Constructor_TaskBoardRequest)
	{
		QString chanName = "chan1";
		QString boardId = "/b/";
		QUrl link("http://chan/b/");
		TaskBoardRequest rq(chanName, boardId, link, "Message", 0);

		ASSERT_EQ(link, rq.link());
		verifyTaskBoardRequest(chanName, boardId, rq);
	}

	TEST_F(TestTaskRequest, Constructor_TaskThreadRequest)
	{
		ThreadId threadId("chan", "/b/", 123456);
		QUrl link("http://chan/b/whatever");
		TaskThreadRequest rq(threadId, link, "Message", 0);

		ASSERT_EQ(link, rq.link());
		verifyTaskThreadRequest(threadId, rq);
	}

	TEST_F(TestTaskRequest, Constructor_TaskAttachmentRequest)
	{
		PostId postId("chan", "/b/", 123456, 123457);
		int attachmentIndex = 12;
		QUrl link("http://chan/b/thumb.jpg");
		TaskAttachmentRequest rq(postId, attachmentIndex, link, "", 0);

		ASSERT_EQ(link, rq.link());
		verifyTaskAttachmentRequest(postId, attachmentIndex, rq);
	}

	TEST_F(TestTaskRequest, start)
	{
		MockRequestPtr request = makeMockRequest();
		MockConnector connector;
		TaskBoardRequest task("chan", "/b/", QUrl("http://chan/b/"), "Message", &connector);
		EXPECT_CALL(connector, makeRequest(_, _, _)).WillOnce(Return(request));
		EXPECT_CALL(connector, queue(_));

		task.start();
	}

	TEST_F(TestTaskRequest, TaskBoardRequest_slot_result)
	{
		MockRequestPtr request = makeMockRequest();
		TaskBoardRequest task("chan", "/b/", QUrl("http://chan/b/"), "Message", 0);
		TaskRequestSignalSpy spy;
		spy.connect(&spy, SIGNAL(signal_result(RequestPtr,QByteArray)), &task, SLOT(slot_result(RequestPtr,QByteArray)));
		task.connect(&task, SIGNAL(result(TaskBoardRequest*,QByteArray,QString)), &spy, SLOT(result(TaskBoardRequest*,QByteArray,QString)));

		int callsBefore = spy.taskBoardRequestCalls();
		spy.emitSignalResult(request, QByteArray());
		int callsAfter = spy.taskBoardRequestCalls();

		ASSERT_EQ(1, callsAfter - callsBefore);
	}

	TEST_F(TestTaskRequest, TaskThreadRequest_slot_result)
	{
		MockRequestPtr request = makeMockRequest();
		TaskThreadRequest task(defaultThreadId, QUrl("http://chan/b/"), "Message", 0);
		TaskRequestSignalSpy spy;
		spy.connect(&spy, SIGNAL(signal_result(RequestPtr,QByteArray)), &task, SLOT(slot_result(RequestPtr,QByteArray)));
		task.connect(&task, SIGNAL(result(TaskThreadRequest*,QByteArray,QString)), &spy, SLOT(result(TaskThreadRequest*,QByteArray,QString)));

		int callsBefore = spy.taskThreadRequestCalls();
		spy.emitSignalResult(request, QByteArray());
		int callsAfter = spy.taskThreadRequestCalls();

		ASSERT_EQ(1, callsAfter - callsBefore);
	}

	TEST_F(TestTaskRequest, TaskAttachmentRequest_slot_result)
	{
		MockRequestPtr request = makeMockRequest();
		int attachmentIndex = 0;
		TaskAttachmentRequest task(defaultPostId, attachmentIndex, QUrl("http://chan/b/"), "Message", 0);
		TaskRequestSignalSpy spy;
		spy.connect(&spy, SIGNAL(signal_result(RequestPtr,QByteArray)), &task, SLOT(slot_result(RequestPtr,QByteArray)));
		task.connect(&task, SIGNAL(result(TaskAttachmentRequest*,QByteArray,QString)), &spy, SLOT(result(TaskAttachmentRequest*,QByteArray,QString)));

		int callsBefore = spy.taskAttachmentRequestCalls();
		spy.emitSignalResult(request, QByteArray());
		int callsAfter = spy.taskAttachmentRequestCalls();

		ASSERT_EQ(1, callsAfter - callsBefore);
	}
}
